#pragma once

#include <string>
#include "../models/usermodel.hpp"
#include "../views/userview.hpp"
#include "../util.hpp"

namespace pharmacy_server
{

    class UserController
    {
    public:
        static UserController& instance()
        {
            static UserController inst;
            return inst;
        }

    private:
        UserController() = default;
        UserController(const UserController&) = delete;
        UserController& operator=(const UserController&) = delete;

    public:
        Result login_user(const std::string& username, const std::string& password, const std::string& role)
        {
            try
            {
                User* user = usermodel.authenticate_user(username, password, role);
                return userview.login_user(user);
            }
            catch (const model_except& e)
            {
                return userview.login_user(false, e.what());
            }
        }

        Result register_user(const std::string& username, const std::string& password, const std::string& role)
        {
            try
            {
                usermodel.create_user(username, password, role);
                return userview.register_user(true, "register success");
            }
            catch (const model_except& e)
            {
                return userview.register_user(false, e.what());
            }
        }

        Result delete_user(const std::string& username)
        {
            try
            {
                if (usermodel.current_user()->role != "admin"
                 && usermodel.current_user()->username != username)
                    return userview.register_user(false, "only admin can delete others");

                User* user = usermodel.find_user(username);

                usermodel.delete_user(username);
                return userview.delete_user(true, "delete success");
            }
            catch (const model_except& e)
            {
                return userview.delete_user(false, e.what());
            }
        }

        Result update_user(const std::string& username, const std::string new_username, const std::string& new_password, const std::string& new_role)
        {
            try
            {
                if (usermodel.current_user()->role != "admin"
                 && usermodel.current_user()->username != username)
                    return userview.register_user(false, "only admin can update others");

                usermodel.update_user(username, new_username, new_password, new_role);
                return userview.update_user(true, "update success");
            }
            catch (const model_except& e)
            {
                return userview.update_user(false, e.what());
            }
        }

        Result current_user()
        {
            try
            {
                User* user = usermodel.current_user();
                return userview.current_user(true, "get current user success", json_util::serialize(user->to_json()));
            }
            catch (const model_except& e)
            {
                return userview.current_user(false, e.what());
            }
        }

        Result logout_user()
        {
            try
            {
                bool succ = usermodel.logout_user();
                return userview.logout_user(succ);
            }
            catch (const model_except& e)
            {
                return userview.logout_user(false, e.what());
            }
        }

        Result get_user(const std::string& username)
        {
            try
            {
                User* user = usermodel.get_user(username);
                return userview.get_user(true, "get user success", json_util::serialize(user->to_json()));
            }
            catch (const model_except& e)
            {
                return userview.get_user(false, e.what());
            }
        }

    private:
        UserModel usermodel;
        UserView userview;
    };

}
